/*
	ggamewin.cc	GRhino Gnome Frontend Game Library Window
	Copyright (c) 2005, 2010 Kriang Lerdsuwanakij
	email:		lerdsuwa@users.sourceforge.net

	This program is free software; you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation; either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program; if not, write to the Free Software
	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
#define GNOME_DISABLE_DEPRECATED
#define GTK_DISABLE_DEPRECATED
*/

#include "config.h"

#include <gtk/gtk.h>
#include <gnome.h>

#include <string>
#include <map>

#include "board.h"
#include "game.h"
#include "gutil.h"
#include "ggamewin.h"

#ifdef _
#undef _
#endif

#ifdef N_
#undef N_
#endif

#include <libintl.h>
#define _(x) gettext(x)
#define N_(x) x

/*************************************************************************
	File menu - Open
*************************************************************************/

int gamelib_width, gamelib_height, gamelib_x, gamelib_y;
int gamelib_win_count;

std::map<std::string, GtkWidget *> gamelib_map;

struct gamelib_resource {
	std::string file;
	GtkWidget *win;
	GtkWidget *tree_view;
	GtkListStore *list_store;
	std::vector<game_library_log> *vec;

	gamelib_resource(const char *f) : file(f), win(0),
				tree_view(0), list_store(0), vec(0) {}
};

void game_library_fill(gamelib_resource *res)
{
	char buf1[20], buf2[20], buf3[50];
	char *buf2ptr, *buf3ptr;
	GtkTreeIter iter;

	for (size_t i = 0; i != res->vec->size(); ++i) {

		snprintf(buf1, 20, "%zd", i+1);

		if (res->vec->operator[](i).random) {
			snprintf(buf2, 20, _("Rand %d"),
				 res->vec->operator[](i).board.get_num_move() + 4);
			buf2ptr = buf2;
		}
		else
			buf2ptr = _("Std");

		if (res->vec->operator[](i).resign) {
			if (res->vec->operator[](i).black_score
			    < res->vec->operator[](i).white_score)
				buf3ptr = _("Black resigned");
			else
				buf3ptr = _("White resigned");
		}
		else if (res->vec->operator[](i).timeout) {
			if (res->vec->operator[](i).black_score
			    < res->vec->operator[](i).white_score)
				buf3ptr = _("Black timeout");
			else
				buf3ptr = _("White timeout");
		}
		else {
			if (res->vec->operator[](i).format == game_log::format_IOS) {
				if (res->vec->operator[](i).black_score
				    < res->vec->operator[](i).white_score)
					snprintf(buf3, 50, _("White won %d-%d"),
						 res->vec->operator[](i).white_score,
						 res->vec->operator[](i).black_score);
				else
					snprintf(buf3, 50, _("Black won %d-%d"),
						 res->vec->operator[](i).black_score,
						 res->vec->operator[](i).white_score);
				buf3ptr = buf3;
			}
			else {
				if (res->vec->operator[](i).black_score
				    < res->vec->operator[](i).white_score)
					snprintf(buf3, 50, _("White won by %d"),
						 res->vec->operator[](i).white_score
						 - res->vec->operator[](i).black_score);
				else
					snprintf(buf3, 50, _("Black won by %d"),
						 res->vec->operator[](i).black_score
						 - res->vec->operator[](i).white_score);
				buf3ptr = buf3;
			}
		}

		gtk_list_store_append(res->list_store, &iter);
		gtk_list_store_set(res->list_store, &iter, 
				   0, i, 
				   1, buf1, 
				   2, res->vec->operator[](i).black_name.c_str(), 
				   3, res->vec->operator[](i).white_name.c_str(),
				   4, buf2ptr,
				   5, buf3ptr, -1);
	}
}

void game_library_update(update_state_type /*u*/, void *d)
{
	gamelib_resource *res = (gamelib_resource *)d;
	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(res->tree_view));
	gtk_tree_selection_unselect_all(selection);
}

gint game_library_configure_event(GtkWidget *widget, 
				  GdkEventConfigure *e, gpointer /*data*/)
{
				// Only update size/position preference if
				// one window is opened
	if (gamelib_win_count == 1) {
		gtk_window_get_position(GTK_WINDOW(widget), &gamelib_x, &gamelib_y);
		gamelib_width = e->width;
		gamelib_height = e->height;
	}
	return FALSE;		// Propagate signal to child so that it
				// can resize itself
}

void game_library_closed(GtkWidget *widget, gamelib_resource *res)
{
	update_game_list.remove(game_library_update, res);

	gtk_widget_destroy(widget);
	gamelib_map.erase(res->file);
	delete res->vec;
	g_object_unref(res->list_store);
	delete res;

	gamelib_win_count--;
}

void game_library_selected(GtkTreeSelection *selection, gamelib_resource *res)
{
	GtkTreeIter iter;
	GtkTreeModel *model;
	if (gtk_tree_selection_get_selected(selection, &model, &iter)) {
		int pos;
		gtk_tree_model_get(model, &iter, 0, &pos, -1);
		update_game_list.update_except(UPDATE_ALL, game_library_update, res);
		load_game(res->vec->operator[](pos));
	}
}

bool game_library_opened(const char *f)
{
	std::string ff = f;
	if (gamelib_map.find(ff) != gamelib_map.end())
		return true;
	else
		return false;
}

void game_library(std::vector<game_library_log> *v, const char *f)
{
	std::string ff = f;
				// Popup window if file already opened
				// Note: v can be 0 in this case
	if (gamelib_map.find(ff) != gamelib_map.end()) {
		gtk_window_present(GTK_WINDOW(gamelib_map[ff]));
		delete v;
		return;
	}

	gamelib_win_count++;

	std::string title = _("Game List - ");
	title += f;

	GtkWidget *gamelib = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_window_set_title(GTK_WINDOW(gamelib), title.c_str());
	gtk_container_set_border_width(GTK_CONTAINER(gamelib), 5);

	GtkListStore *list_store_gamelib = gtk_list_store_new(
						6, G_TYPE_INT, G_TYPE_STRING, 
						G_TYPE_STRING, G_TYPE_STRING,
						G_TYPE_STRING, G_TYPE_STRING);
	GtkWidget *tree_view_gamelib
		= gtk_tree_view_new_with_model(GTK_TREE_MODEL(list_store_gamelib));

				// Keep information for resource release
				// when window is closed
	gamelib_resource *res = new gamelib_resource(f);
	res->vec = v;
	res->win = gamelib;
	res->list_store = list_store_gamelib;
	res->tree_view = tree_view_gamelib;

				// Remember that this file is opened
	gamelib_map[ff] = gamelib;

	g_signal_connect(G_OBJECT(gamelib), "destroy",
			 G_CALLBACK(game_library_closed), res);
	g_signal_connect(G_OBJECT(gamelib), "configure_event",
			 G_CALLBACK(game_library_configure_event), NULL);

	GtkWidget *scroll = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll),
				       GTK_POLICY_NEVER,
				       GTK_POLICY_AUTOMATIC);
	if (gamelib_x != -1 && gamelib_y != -1
	    && gamelib_win_count == 1)
		gtk_window_move(GTK_WINDOW(gamelib), gamelib_x, gamelib_y);
	gtk_window_set_default_size(GTK_WINDOW(gamelib), gamelib_width, gamelib_height);
	gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll),
					    GTK_SHADOW_ETCHED_IN);
	gtk_container_add(GTK_CONTAINER(gamelib), scroll);

	GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
	g_object_set(G_OBJECT(renderer), "xalign", 1.0, NULL);	// Right aligned
	GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
						_("No"),
						renderer,
						"text", 1,
						NULL);
	gtk_tree_view_column_set_sort_column_id(column, 0);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_gamelib),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						_("Black"),
						gtk_cell_renderer_text_new(),
						"text", 2,
						NULL);
	gtk_tree_view_column_set_sort_column_id(column, 2);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_gamelib),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						_("White"),
						gtk_cell_renderer_text_new(),
						"text", 3,
						NULL);
	gtk_tree_view_column_set_sort_column_id(column, 3);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_gamelib),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						_("Type"),
						gtk_cell_renderer_text_new(),
						"text", 4,
						NULL);
	gtk_tree_view_column_set_sort_column_id(column, 4);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_gamelib),
				    column);
	column = gtk_tree_view_column_new_with_attributes(
						_("Result"),
						gtk_cell_renderer_text_new(),
						"text", 5,
						NULL);
	gtk_tree_view_column_set_sort_column_id(column, 5);
	gtk_tree_view_append_column(GTK_TREE_VIEW(tree_view_gamelib),
				    column);

	gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_view_gamelib),
					  TRUE);
	gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree_view_gamelib), TRUE);

	GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_view_gamelib));
	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
	g_signal_connect(G_OBJECT(selection), "changed",
			 G_CALLBACK(game_library_selected), res);

	gtk_container_add(GTK_CONTAINER(scroll), tree_view_gamelib);

	game_library_fill(res);

	gtk_widget_show_all(gamelib);

	GtkTreePath *path = gtk_tree_path_new();
	gtk_tree_path_append_index(path, 0);
	gtk_tree_selection_select_path(selection, path);
	gtk_tree_view_scroll_to_cell(GTK_TREE_VIEW(tree_view_gamelib), path, 
				     NULL, FALSE, 0, 0);
	gtk_tree_view_set_cursor(GTK_TREE_VIEW(tree_view_gamelib), path, 
				 NULL, FALSE);
	gtk_tree_path_free(path);

	update_game_list.update(UPDATE_ALL);
	update_game_list.add(game_library_update, res);
}
